<?php
/**
 * Класс, содержащий вспомогательные для проекта методы
 */
class Ext_App
{
    const LOG_PAGE_NOT_FOUND = 1;
    const LOG_ACCESS_DENIED  = 2;
    const LOG_APP_ERROR      = 3;
    const LOG_APP_WARN       = 4;

    protected static $stackTraceStopClasses = array(
        'Zend_Controller_Front',
        'Zend_Controller_Dispatcher_Standard',
        'Zend_Controller_Action',
    );
    
    /**
     * @var Zend_Controller_Action_Helper_Abstract
     */
    protected static $_settingsHelper;


    /**
     * Возвращает опцию настроек из базы данных или settings.ini
     * @param string $settingName
     * @return mixed
     */
    public static function getSetting($settingName)
    {
        if (!$settingName) {
            return null;
        }
        return self::_getSettingsHelper()->get($settingName);
    }

    /**
     * возвращает объект статического хелпера настроек
     * @return Zend_Controller_Action_Helper_Abstract
     */
    protected static function _getSettingsHelper()
    {
        if (!self::$_settingsHelper) {
            self::$_settingsHelper = Zend_Controller_Action_HelperBroker::getStaticHelper('settings');
        }
        return self::$_settingsHelper;
    }

    /**
     * @param array $report
     *      format: array (
     *          'exception' => Zend_Controller_Dispatcher_Exception,
     *          'request'   => Zend_Controller_Request_Http,
     *          'member'    => Model_Member,
     *          'ip'        => string (e.g. '192.168.0.1')
     *      )
     * @param int $type (@see constants)
     * @return void
     */
    public static function log($report, $type = self::LOG_APP_ERROR)
    {
        if ( sizeof($report) == 0 || !is_numeric($type) ) {
            return;
        }

        $record = $report['exception']->getMessage();
        /*
        $mail = array(
            'recipient' => Model_MailQueue::RECIPIENT_DEVELOPERS,
            'subject'   => 'Error report',
            'mailBody'  => array(
                'exception' => $report['exception']
            ),
            'template'  => Model_MailQueue::TEMPLATE_ERROR_NOTIFICATION,
            'priority'  => Model_MailQueue::PRIORITY_HIGH
        );
        */
        if (isset($report['request']) && $report['request'] instanceof Zend_Controller_Request_Http) {
//            $mail['mailBody']['request'] = $report['request'];

            if ($report['request']->getParam('content') instanceof Core_Model_PirRecord) {
                $report['request']->setParam('content', $report['request']->getParam('content')->toArray(false));
            }
            $record .= ', Request: ' . var_export($report['request']->getParams(), true);
        }
        if (isset($report['ip']) && !empty($report['ip'])) {
//            $mail['mailBody']['ip'] = $report['ip'];
            $record .= ', UserIP: ' . $report['ip'];
        }
        if (isset($report['exception']) && !empty($report['exception'])) {
            $traceStr = self::smartTraceAsString($report['exception']);
            $record .=  ", Stack Trace:\n$traceStr\n";
        }

        switch ($type) {
            case self::LOG_APP_ERROR:

                $logFile = Core_App::getSetting('logs.path') . '/' . 'error.log';
//                Model_MailQueue::addToQueue($mail);
                break;
            case self::LOG_ACCESS_DENIED:
                $logFile = Core_App::getSetting('logs.path') . '/' . 'access_denied.log';
                break;
            case self::LOG_APP_WARN:
                $logFile = Core_App::getSetting('logs.path') . '/' . 'warnings.log';
                break;
            default:
                $logFile = Core_App::getSetting('logs.path') . '/' . 'page_not_found.log';
        }
        $writer = new Zend_Log_Writer_Stream($logFile);
        $logger = new Zend_Log($writer);
        $logger->log($record, $type);
    }

    public static function smartTraceAsString(Exception $e)
    {
        $traceStr = '';
        foreach ($e->getTrace() as $lineIndex => $line) {
            $args = '';
            if (isset($line['args']) && !empty($line['args'])) {
                $args  = self::print_r_light($line['args']);
            }
            $traceStr .= $lineIndex . '. ' . (isset($line['class']) ? $line['class'] : '')
                . (isset($line['type']) ? $line['type'] : '') . $line['function'] . "($args)";
            if (isset($line['file']) && isset($line['line'])) {
                $stripPaths = array(realpath(APPLICATION_PATH));
                foreach (explode(';', get_include_path()) as $path) {
                    $stripPaths[] = realpath($path);
                }
                $line['file'] = str_replace($stripPaths, '', $line['file']);
                $traceStr .= "\n\tin {$line['file']} ({$line['line']})";
            }
            $traceStr .= "\n";
            if (isset($line['class']) && in_array($line['class'], self::$stackTraceStopClasses)) {
                $traceStr .= "...\n";
                break;
            }
        }
        return $traceStr;
    }

    public static function print_r_light($array, $str = '', $deepLevel = 1)
    {
        if (empty($array)) {
            return '';
        }
        if ($deepLevel > 2) {
            return '...';
        }
        foreach($array as $key => $arg) {
            if (is_null($arg)) {
                $arg = 'NULL';
            } elseif ($arg === true) {
                $arg = 'true';
            } elseif ($arg === false) {
                $arg = 'false';
            } elseif (is_string($arg)) {
                if (strlen($arg > 400)) {
                    $arg = substr($arg, 0, 150);
                    $arg .= '...';
                }
                $arg = "'$arg'";
            } elseif (is_object($arg)) {
                $arg = 'object of ' . get_class($arg);
            } elseif (is_array($arg)) {
                $arg = 'array(' . self::print_r_light($arg, $str, $deepLevel + 1) . ')';
            }
            $str .= ($deepLevel > 1 && !is_numeric($key) ? $key . ' => ' : '') . $arg . ', ';
        }
        return substr($str, 0, -2);
    }

    /**
     * Склеивает элементы массива безопасно с точки зрения вставки в сырой запрос
     * @param array $array
     * @return string
     */
    public static function escapeImplodeArray($array, $glue = ', ')
    {
        return implode($glue, array_map(
            function($value) {
                $search = array("\\","\0","\n","\r","\x1a","'",'"');
                $replace = array("\\\\","\\0","\\n","\\r","\Z","\'",'\"');
                return str_replace($search, $replace, $value);
            }, $ids))
        ;
    }

    /**
     * @param string $tableName
     * @return Ext_Model_DbTable_Abstract
     */
    public static function getTable($tableName)
    {
        return class_exists($tableName) ? new $tableName() : null;
    }

    /**
     * @param string $salt
     * @return string
     */
    public static function getToken($salt = null)
    {
        return md5($salt . substr(md5(time()), rand(1, 20), rand(5, 10)));
    }

    /**
     * @param int $length
     * @return string
     */
    public static function getSalt($length = 8)
    {
        return substr(self::getToken('password-salt'), 0, $length);
    }
}